#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <pthread.h>
#include "ca1fw.h"
#include"/home/shubhanshu/Downloads/framework/ca1fw/include/ca1fw.h"
 struct my_q                                        //The structure for system message queue which is used as a buffer for the incoming requests
{
    long mtype;
    REQUEST req;
};
int qid1,qid2;                                      //queue identifiers
struct my_q write_q;                                //The write buffer
struct my_q read_q1,read_q2;                        //The read buffer
key_t key;                                          //Message Queue ID
key_t key1;                                         //Message Queue Key

//Function to write the request into the queue

void * write_Request (void * nothing)
{
  startFramework() ;                                 //start the framework

        while (! noMoreRequests())
        {    if(isRequestAvailable()==1)
             {
                write_q.req=getRequest();
               if(getDB(write_q.req)==1)
               {

                    msgsnd(qid1, &write_q, sizeof(REQUEST),0); //Push incoming packets to the queue for db1
               }
               else
               {
                   if(msgsnd(qid2, &write_q, sizeof(REQUEST), 0)==-1) //Push incoming packets to the queue for db2
                             perror("msgsnd error");
               }
              }
        usleep(5);
         }
  pthread_exit(NULL);
  }

//Function to read requests form the queue for db1

void * read_Requestdb1(void* nothing)
{
      while (! noMoreRequests())
        {
        msgrcv(qid1, &read_q1, sizeof(REQUEST), 1, 0); //Read the request from the queue
        int db=getDB(read_q1.req);                     //Get the db number
        int feed=getFeed(read_q1.req);                 //Get the feed number
        MSISDN user=getUser(read_q1.req);              //Get the user
        if(db==1 && user!=ERROR && feed!=ERROR)        //Checking the conditions
        {

               RESPONSE rsp=getData(db,feed);           //retrives the data
               sendResponse(user,rsp);                  //sends the response to the user
        }
        usleep(10);                                     //thread sleep
    }

    pthread_exit(NULL);
}

//Function to read requests form the queue for db2
void * read_Requestdb2(void* nothing)
{
      while(!noMoreRequests())
      {
        msgrcv(qid2, &read_q2, sizeof(REQUEST), 1, 0);
        int db=getDB(read_q2.req);
        int feed=getFeed(read_q2.req);
        MSISDN user=getUser(read_q2.req);
        if(db==2 && user!=ERROR && feed!=ERROR)
        {
               RESPONSE rsp=getData(db,feed);
               sendResponse(user,rsp);
        }

        usleep(10);
      }
    pthread_exit(NULL);

}

//Main Program

int main(void)
{
    pthread_t receive_request;
    pthread_t decode_db1;
    pthread_t decode_db2;
    if ((key = ftok("ca1.c", 'b')) == -1)     //creating the key for the queue
        {
		perror("ftok");
		exit(1);
	}
    msgctl(qid1, IPC_RMID, NULL);
	if ((qid1 = msgget(key, 0644 | IPC_CREAT)) == -1) //creating the system queue
        {
		perror("msgget");
		exit(1);
	}

    if((key1 = ftok("ca1.c", 'c'))== -1)
    {
        perror("ftok");
        exit(1);
    }
    msgctl(qid2, IPC_RMID, NULL);
	if ((qid2 = msgget(key1, 0644 | IPC_CREAT)) == -1)
        {
		perror("msgget");
		exit(1);

	}
    write_q.mtype=1;
    pthread_create(&receive_request, NULL, write_Request, NULL);  //creating a thread to receive packet
    pthread_create(&decode_db1, NULL, read_Requestdb1, NULL);     //creating a thread for the db1
    pthread_create(&decode_db2,NULL,read_Requestdb2,NULL);        //creating a thread for the db2
    pthread_join(receive_request,NULL);
    pthread_join(decode_db1,NULL);
    pthread_join(decode_db2,NULL);
    msgctl(qid1, IPC_RMID, NULL);                                 //deletes the message queue
    msgctl(qid2, IPC_RMID, NULL);
    stopFramework();                                              //stop the framework
    return 0;
}
